import java.awt.*;
import java.util.Random;
import javax.swing.*;

/**
 * Rendering 游戏渲染类
 *
 * @author 烦得很
 */
public class Rendering {
    private final int maxUpdateTime = 500; // 最大刷新时间
    private final int minUpdateTime = 100; // 最小刷新时间
    private int gameMapWidth = 20; // 地图宽
    private int gameMapHeight = 20; // 地图高
    private final Color wallColor = Color.black; // 墙的颜色
    private final Color canGoSpaceColor = Color.white; // 可以行走区块的颜色
    private final Color snackHeadColor = Color.green; // 蛇头的颜色
    private final Color snackBodyColor = Color.yellow; // 蛇身的颜色
    private final Color appleColor = Color.red; // 苹果的颜色
    private JFrame gameFrame; // 游戏窗口
    private JPanel scoresUI; // 分数ui
    private JPanel mainGamePanel; // 主游戏ui
    private JPanel gameOverUI; // 游戏结束窗口
    private JLabel scorelabel = new JLabel(); // 分数信息
    private JLabel isDiedInformation = new JLabel(); // 死亡信息


    /**
     * 初始化游戏
     */
    public Rendering() {
        initializationGame();
    }

    /**
     * 初始化游戏
     */
    public Rendering(int mapSize) {
        // 设置地图大小
        gameMapWidth = mapSize;
        gameMapHeight = mapSize;
        initializationGame();
    }

    /**
     * 初始化游戏窗口
     */
    private void initializationGame() {
        // 初始化游戏窗口
        gameFrame = new JFrame("贪吃蛇");
        gameFrame.setLayout(null);
        gameFrame.setSize(515, 700);
        // 初始化分数ui
        scoresUI = new JPanel(new FlowLayout());
        scoresUIInitialization();
        // 初始化游戏运行区域
        mainGamePanel = new JPanel(new GridLayout(gameMapHeight, gameMapWidth));
        mainGamePanelInitialization();
        // 初始化游戏状态的ui
        gameOverUI = new JPanel();
        gameOverUIInitialization();
        // 把各ui加入游戏窗口
        gameFrame.add(mainGamePanel);
        gameFrame.add(scoresUI);
        gameFrame.add(gameOverUI);
        gameFrame.setVisible(true);
    }


    /**
     * 获取焦点
     */
    public void requestForce() {
        gameFrame.requestFocus();
    }

    /**
     * 获取最小刷新时间
     *
     * @return 最小刷新时间
     */
    public int getMinUpdateTime() {
        return minUpdateTime;
    }

    /**
     * 获取最大刷新时间
     *
     * @return 最大刷新时间
     */
    public int getMaxUpdateTime() {
        return maxUpdateTime;
    }

    /**
     * 获取地图大小
     *
     * @return 地图大小[宽，高]
     */
    public int[] getMapSize() {
        return new int[]{gameMapWidth, gameMapHeight};
    }

    /**
     * 获取墙的颜色
     *
     * @return 墙的颜色
     */
    public Color getWallColor() {
        return wallColor;
    }

    /**
     * 获取可以走的普通区域的颜色
     *
     * @return 普通可过区域颜色
     */
    public Color getCanGoSpaceColor() {
        return canGoSpaceColor;
    }

    /**
     * 获取蛇头颜色
     *
     * @return 蛇头颜色
     */
    public Color getSnackHeadColor() {
        return snackHeadColor;
    }

    /**
     * 获取蛇身颜色
     *
     * @return 蛇身颜色
     */
    public Color getSnackBodyColor() {
        return snackBodyColor;
    }

    /**
     * 获取苹果颜色
     *
     * @return 苹果颜色
     */
    public Color getAppleColor() {
        return appleColor;
    }

    /**
     * 初始化gameOverUI
     */
    private void gameOverUIInitialization() {
        gameOverUI.setBounds(0, 600, 500, 50);
        isDiedInformation.setText("游戏进行中");
        gameOverUI.add(isDiedInformation);
    }

    /**
     * 游戏结束ui显示
     */
    public void gameOverUIChange() {
        isDiedInformation.setText("游戏结束");
    }

    /**
     * 分数ui初始化
     */
    private void scoresUIInitialization() {
        scoresUI.setSize(500, 30);
        scoresUI.setBackground(Color.GREEN);
        scoresUI.add(scorelabel);
        scoreUIChange(0);
    }

    /**
     * 游戏地图初始化
     */
    private void mainGamePanelInitialization() {
        mainGamePanel.setBounds(0, 50, 500, 500);
        for (int i = 0; i < gameMapWidth * gameMapHeight; i++) {
            JPanel block = new JPanel();
            block.setSize(500 / gameMapWidth, 500 / gameMapHeight);
            block.setBackground(canGoSpaceColor);
            mainGamePanel.add(block);
        }
        // 墙体绘制
        boolean isWall = false;
        for (int i = 0; i < gameMapHeight * gameMapWidth; i++) {
            if (i <= gameMapWidth - 1) {
                isWall = true;
            } else if (i % gameMapWidth == 0) {
                isWall = true;
            } else if (i == (i / gameMapWidth + 1) * gameMapWidth - 1) {
                isWall = true;
            } else if (i > (gameMapHeight * gameMapWidth) - gameMapWidth - 1) {
                isWall = true;
            }
            if (isWall) {
                mainGamePanel.getComponent(i).setBackground(wallColor);
                isWall = false;
            }
        }
    }

    /**
     * 画分数显示ui,改变分数
     *
     * @param score 更改的目标分数
     */
    public void scoreUIChange(int score) {
        scorelabel.setText("scores:" + score);
    }

    /**
     * 判断游戏区块，如果合法便绘制蛇头
     *
     * @param raw 行，1开始
     * @param col 列，1开始
     * @return 目标区块颜色
     */
    public Color drawSnackHead(int raw, int col) {
        Component targetArea = mainGamePanel.getComponent((raw - 1) * gameMapHeight + col - 1);
        // System.out.println((raw - 1) + " " + (col - 1));
        Color targetColor = targetArea.getBackground();
        boolean isCanGo = targetColor.equals(canGoSpaceColor) || targetColor.equals(appleColor);
        if (isCanGo) {
            // System.out.println(targetArea.getBackground());
            targetArea.setBackground(snackHeadColor);
            // System.out.println(targetArea.getX() + " " + targetArea.getY() + " " +
            // targetArea.getBackground());
        }
        return targetColor;
    }

    /**
     * 绘制苹果
     */
    public void putApple() {
        int max = getMapSize()[0] * getMapSize()[1] - 1;
        Random random = new Random();
        while (true) {
            int target = random.nextInt(max);
            if (getAreaColor(target).equals(getCanGoSpaceColor())) {
                drawArea(target, getAppleColor());
                return;
            }
        }
    }

    /**
     * 蛇身渲染
     *
     * @param snackAll 全蛇坐标
     * @param top      栈顶，蛇尾
     */
    public void drawSnackAllBody(int[][] snackAll, int top) {
        for (int i = 1; i <= top; i++) {
            int n = (snackAll[i][0] - 1) * gameMapHeight + (snackAll[i][1] - 1);
            drawArea(n, snackBodyColor);
        }
    }

    /**
     * 强制性质的画区块
     *
     * @param raw         行，1开始
     * @param col         列，1开始
     * @param targetColor 目标颜色
     */
    public void drawArea(int raw, int col, Color targetColor) {
        Component targetArea = mainGamePanel.getComponent((raw - 1) * gameMapHeight + col - 1);
        targetArea.setBackground(targetColor);
    }

    /**
     * 强制性质的画区块
     *
     * @param n           目标区块索引
     * @param targetColor 目标颜色
     */
    public void drawArea(int n, Color targetColor) {
        Component targetArea = mainGamePanel.getComponent(n);
        targetArea.setBackground(targetColor);
    }

    /**
     * 强制性质的画蛇身
     *
     * @param raw 行，1开始
     * @param col 列，1开始
     */
    public void drawArea(int raw, int col) {
        Component targetArea = mainGamePanel.getComponent((raw - 1) * gameMapHeight + col - 1);
        targetArea.setBackground(snackBodyColor);
    }

    /**
     * 强制性质的画蛇身
     *
     * @param position 目标位置
     */
    public void drawArea(int[] position) {
        Component targetArea = mainGamePanel.getComponent((position[0] - 1) * gameMapHeight + position[1] - 1);
        targetArea.setBackground(snackBodyColor);
    }

    /**
     * 强制性质的画区块
     *
     * @param position    目标位置
     * @param targetColor 目标颜色
     */
    public void drawArea(int[] position, Color targetColor) {
        Component targetArea = mainGamePanel.getComponent((position[0] - 1) * gameMapHeight + position[1] - 1);
        targetArea.setBackground(targetColor);
    }

    /**
     * 获取指定位置颜色
     *
     * @param raw 行，1开始
     * @param col 列，1开始
     * @return 目标颜色
     */
    public Color getAreaColor(int raw, int col) {
        return mainGamePanel.getComponent((raw - 1) * gameMapHeight + col - 1).getBackground();
    }

    /**
     * 获取指定目标颜色
     *
     * @param n 区块索引
     * @return 目标颜色
     */
    public Color getAreaColor(int n) {
        return mainGamePanel.getComponent(n).getBackground();
    }
}
